﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.TeamFoundation.TestManagement.Client;
using Microsoft.TeamFoundation.Lab.Client;
using HybridLab.Workflow.Activities.Info;
using HybridLab.Virtual.Interfaces;

namespace HybridLab.Workflow.Activities.UI
{
	internal partial class EnvironmentPage : UserControl
	{
		private HybridLabWizardData wizardData;
		private ErrorProvider environmentErrorProvider;
		private ErrorProvider hostErrorProvider;
		private bool isFirstLoad = true;

		public EnvironmentPage(HybridLabWizardData wizardData)
		{
			if (wizardData == null)
			{
				throw new ArgumentNullException("wizardData");
			}
			InitializeComponent();
			this.wizardData = wizardData;
			wizardData.DataLoadCompleted += new EventHandler(wizardData_DataLoadCompleted);
		}

		void wizardData_DataLoadCompleted(object sender, EventArgs e)
		{
			PopulateEnvironments();
            InitializeErrorProviders();
			
            UpdateUI();
            RefreshErrors();
			isFirstLoad = false;
        }

        private void UpdateUI()
        {
			var currentEnvId = wizardData.EnvironmentDetails.Environment == null ? Guid.Empty : wizardData.EnvironmentDetails.Environment.Id;
			if (currentEnvId != Guid.Empty)
			{
				foreach (ITestEnvironment env in cmbEnvironments.Items)
				{
					if (env.Id == currentEnvId)
					{
						cmbEnvironments.SelectedItem = env;
						break;
					}
				}
			}
			else
			{
				wizardData.EnvironmentDetails.Environment = null;
			}

			txtPass.Text = wizardData.EnvironmentDetails.InteractiveUserPassword;
			chkRestoreSnapshot.Checked = wizardData.EnvironmentDetails.RevertToSnapshot;
        }

        private void PopulateEnvironments()
		{
			cmbEnvironments.Items.Clear();
			cmbEnvironments.DisplayMember = "DisplayName";
			if (wizardData.Environments != null)
			{
				cmbEnvironments.Items.AddRange(wizardData.Environments.OrderBy(le => le.Name).ToArray());
			}
		}

		private void InitializeErrorProviders()
		{
			environmentErrorProvider = WizardUtils.CreateErrorProvider(cmbEnvironments);
			hostErrorProvider = WizardUtils.CreateErrorProvider(btnConnectToHost);
		}

        private void cmbEnvironments_SelectedIndexChanged(object sender, EventArgs e)
        {
            wizardData.EnvironmentDetails.Environment = cmbEnvironments.SelectedItem as ITestEnvironment;
			LoadSnapshots();
			RefreshErrors();
        }

		private void RefreshErrors()
		{
			environmentErrorProvider.SetError(cmbEnvironments, wizardData.EnvironmentDetails["Environment"]);
			hostErrorProvider.SetError(btnConnectToHost, wizardData.EnvironmentDetails["Host"]);
		}

		private void chkRestoreSnapshot_CheckedChanged(object sender, EventArgs e)
		{
			grpSnapshotInfo.Visible = chkRestoreSnapshot.Checked;
			if (chkRestoreSnapshot.Checked)
			{
				txtHostName.Text = wizardData.EnvironmentDetails.HostName;
				LoadSnapshots();
			}
			wizardData.EnvironmentDetails.RevertToSnapshot = chkRestoreSnapshot.Checked;
			RefreshErrors();
		}

		private void btnConnectToHost_Click(object sender, EventArgs e)
		{
			var hostType = wizardData.EnvironmentDetails.HostType;
			var hostName = wizardData.EnvironmentDetails.HostName;
			var domain   = wizardData.EnvironmentDetails.Credentials.DomainName;
			var username = wizardData.EnvironmentDetails.Credentials.UserName;
			var password = wizardData.EnvironmentDetails.Credentials.Password;

			var connectToHostForm = new ConnectToVirtualHostForm(hostType, hostName, domain, username, password);
			connectToHostForm.Top = Top + 10;
			connectToHostForm.Left = Left + 10;
			var result = connectToHostForm.ShowDialog();
			IVirtualHost host = null;
			if (result == DialogResult.OK)
			{
				host = connectToHostForm.Host;
				wizardData.EnvironmentDetails.HostType = host.HostType;
				wizardData.EnvironmentDetails.HostName = host.HostName;
				wizardData.EnvironmentDetails.Credentials = new HybridLabHostCredentials()
				{
					DomainName = host.Domain,
					UserName = host.UserName,
					Password = host.Password
				};
				LoadSnapshots(host);
			}
			else
			{
				wizardData.EnvironmentDetails.HostName = null;
				gridSnapshots.Rows.Clear();
			}
		}

		private void LoadSnapshots()
		{
			if (string.IsNullOrEmpty(wizardData.EnvironmentDetails.HostName))
			{
				LoadSnapshots(null);
			}
			else
			{
				var host = VirtualHostCatalog.GetHost(wizardData.EnvironmentDetails.HostType, wizardData.EnvironmentDetails.HostName,
					wizardData.EnvironmentDetails.Credentials.DomainName, wizardData.EnvironmentDetails.Credentials.UserName, wizardData.EnvironmentDetails.Credentials.Password);
				LoadSnapshots(host);
			}
		}

		private void LoadSnapshots(IVirtualHost host)
		{
			gridSnapshots.Rows.Clear();

			if (host == null)
			{
				txtHostName.Text = "";
				return;
			}
			else
			{
				txtHostName.Text = host.HostName;
			}
			
			var vms = host.GetVMs();
			var lab = wizardData.EnvironmentDetails.Environment.GetLab(wizardData.Server);
			lab.ToList().ForEach(machine =>
			{
				var row = new DataGridViewRow();
				row.Cells.Add(new DataGridViewTextBoxCell() { Value = machine.Name });

				var combo = new DataGridViewComboBoxCell();
				var snaps = vms.Single(vm => vm.Name.ToLower() == machine.Name.ToLower()).Snapshots;
				snaps.Insert(0, "<<None>>");
				combo.DataSource = snaps;

				var existing = wizardData.EnvironmentDetails.SnapshotInfo.Snapshots.FirstOrDefault(s => s.MachineName == machine.Name);
				if (existing == null)
				{
					wizardData.EnvironmentDetails.SnapshotInfo.AddMachineSnapshot(machine.Name, null);
					combo.Value = "<<None>>";
				}
				else
				{
					if (snaps.Contains(existing.SnapshotName))
					{
						combo.Value = existing.SnapshotName;
					}
					else
					{
						combo.Value = "<<None>>";
					}
				}
				row.Cells.Add(combo);
				gridSnapshots.Rows.Add(row);
			});
			RefreshErrors();
		}

		private void gridSnapshots_CellValueChanged(object sender, DataGridViewCellEventArgs e)
		{
			if (isFirstLoad) return;

			if (e.RowIndex >= 0)
			{
				wizardData.EnvironmentDetails.SnapshotInfo.Clear();
				foreach (DataGridViewRow row in gridSnapshots.Rows)
				{
					var machine = row.Cells[0].Value.ToString();
					var snap = row.Cells[1].Value.ToString();
					if (snap == "<<None>>")
					{
						snap = null;
					}
					wizardData.EnvironmentDetails.SnapshotInfo.AddMachineSnapshot(machine, snap);
				}
			}
		}

		private void txtPass_TextChanged(object sender, EventArgs e)
		{
			wizardData.EnvironmentDetails.InteractiveUserPassword = txtPass.Text;
		}
	}
}
